#include "gateway/beast_http/request_adapter.hpp"
#include <boost/algorithm/string.hpp>
#include <boost/algorithm/string/split.hpp>
#include <boost/algorithm/hex.hpp>
#include <iterator>
#include <cstddef>

using namespace cpp_backend::framework;
namespace http = boost::beast::http;

namespace gateway::beast_http {

namespace {

std::string decode_component(const std::string& input) {
    std::string result;
    result.reserve(input.size());
    for (std::size_t i = 0; i < input.size();) {
        if (input[i] == '%' && i + 2 < input.size()) {
            std::string decoded;
            try {
                boost::algorithm::unhex(
                    input.begin() + static_cast<std::ptrdiff_t>(i + 1),
                    input.begin() + static_cast<std::ptrdiff_t>(i + 3),
                    std::back_inserter(decoded));
            } catch (...) {
                decoded.clear();
            }
            if (!decoded.empty()) {
                result.push_back(decoded[0]);
                i += 3;
                continue;
            }
        }
        result.push_back(input[i] == '+' ? ' ' : input[i]);
        ++i;
    }
    return result;
}

} // namespace

Request RequestAdapter::ToFramework(
    const http::request<http::string_body>& req,
    const std::string& client_ip,
    const std::string& request_id) {
    Request r;
    r.SetMethod(req.method_string().to_string());
    const std::string target = std::string(req.target());
    auto path_end = target.find('?');
    r.SetPath(path_end == std::string::npos ? target : target.substr(0, path_end));
    for (auto const& field : req) {
        r.SetHeader(field.name_string().to_string(), field.value().to_string());
    }
    // 简单解析 query（可按需优化）
    if (path_end != std::string::npos) {
        const std::string query = target.substr(path_end + 1);
        std::vector<std::string> pairs;
        boost::split(pairs, query, boost::is_any_of("&"), boost::token_compress_off);
        for (const auto& pair : pairs) {
            if (pair.empty()) continue;
            std::vector<std::string> kv;
            boost::split(kv, pair, boost::is_any_of("="), boost::token_compress_off);
            if (kv.empty()) continue;
            const std::string key = decode_component(kv[0]);
            const std::string value = kv.size() > 1 ? decode_component(kv[1]) : std::string();
            if (!key.empty()) {
                r.SetParam(key, value);
            }
        }
    }
    // Body（JSON）
    if (!req.body().empty()) {
        try {
            auto j = nlohmann::json::parse(req.body());
            r.SetBody(j);
        } catch (...) {
            // 非JSON忽略
        }
    }
    r.SetClientIp(client_ip);
    r.SetRequestId(request_id);
    return r;
}

} // namespace gateway::beast_http
